# -*- coding: utf8 -*-
# This file is part of pyDC software
# Copyright 2002-2003 Anakim Border <aborder@users.sourceforge.net>
#
# pyDC is released under the terms of GPL licence.
# modified by Pavel C <pavelch+dcbot@gmail.com>
# src site: https://code.google.com/p/dc-bot/

from AsyncSocket import *
from EventGenerator import *
from Job import *
from DNS import DNSError
from DCChallenge import *
#from DCFileList import *
from DCUser import *
#from DCXfer import *
from socket import inet_aton, error
#from threading import Lock
import time
import DCWorker
from collections import deque

class DCHub(object, Job, EventGenerator):
	STATUS_CONNECTING = 1
	STATUS_CONNECTED = 2
	STATUS_CLOSED = 3

	LOG_STATUS = 1
	LOG_CHAT = 2
	LOG_PRIVCHAT = 3
	LOG_ERROR = 4
	

	USER_NORMAL = 1
	USER_FILESERVER = 4
	USER_SPEEDUSER = 8
	USER_AWAY_FLAG = 2

	MAX_LOG_ROWS = 20 #2000
	RECONNECTION_DELAY = 30

	def __init__(self, addr):
		EventGenerator.__init__(self)

		self._addr = None
		self._status = 0
		self.logged = 0
		self.log=DCLog(DCWorker.getWorker().logdir)
		#DCWorker.getWorker().user.nick 
		self.userNick = DCWorker.getWorker().user.nick
		self.userPasswd = ''
		self.userStatus = DCHub.USER_NORMAL
		self.op=0
		self.delay = None
		self._users = {}
		self._log = []
		self.opLock = Lock()
		settings = DCWorker.getWorker().getSettings()
		self.codePage=settings.getCodePage()
		self.awayMsg=settings.getAwayMsg()
		self.lasttime=int(time.time())
		#self.queue = deque()
		

		#hub=['adress','nick','passwd']
		for hub in settings.getHubs():
			if hub[0]==addr:
				self.userNick = hub[1]
				self.userPasswd = hub[2]
				break

		self._addr = self.parseAddress(addr)
		self.reset()	
		self.bot=DCBot(self,settings)	

	def getUserNick(self):
		return self.userNick
	def getLog(self):
		return self.log
	def reset(self):
		if self._addr != None:
			self._name = self._addr[0]
		else:
			self._name = 'unknown'
		self.sock = None
		self._size = long(0)
		self.cmdQueue = []
		self.buf = ''

	def disconnect(self):
		self.stop()

	def startSearch(self, search, active):
		self.opLock.acquire()

		worker = DCWorker.getWorker()
		cmd = '$Search '
		if active:
			cmd += '%s:%d ' % (worker.getLocalAddress(), worker.getSettings().port)
		else:
			cmd += 'Hub:%s ' % self.userNick

		cmd += 'F?F?0?1?'
		for i in search.getPattern().split(' '):
			cmd += i + "$"

		self.cmdQueue.append(cmd[:-1] + '|')
		self.opLock.release()

	def requireConnection(self, nick):
		self.opLock.acquire()
		worker = DCWorker.getWorker()

		if worker.getSettings().active:
			self.cmdQueue.append('$ConnectToMe %s %s:%d|' % (nick, worker.getLocalAddress(), worker.getSettings().port))
		else:
			self.cmdQueue.append('$RevConnectToMe %s %s|' % (self.userNick, nick))

		self.opLock.release()

	def updateInfo(self):
		info = self.buildInfo()
		self.appendLogRow(self.LOG_STATUS, 'Updating user info...')

		self.opLock.acquire()
		self.cmdQueue.append('$MyINFO %s' % info)
		self.opLock.release()

	def setAway(self, away):
		if away:
			if self.userStatus & DCHub.USER_AWAY_FLAG:
				return
			else:
				txt = 'on'
				self.userStatus += DCHub.USER_AWAY_FLAG
		else:
			if self.userStatus & DCHub.USER_AWAY_FLAG:
				txt = 'off'
				self.userStatus -= DCHub.USER_AWAY_FLAG
			else:
				return

		info = self.buildInfo()
		self.appendLogRow(self.LOG_STATUS, 'Away flag: %s.' % txt)

		self.opLock.acquire()
		self.cmdQueue.append('$MyINFO %s' % info)
		self.opLock.release()

	def sendMsg(self, msg, nick=None):
		if self._status != 2:
			self.appendLogRow(self.LOG_ERROR, 'You must be connected to send messages.')
			return

		self.opLock.acquire()
		if nick == None:
			self.cmdQueue.append('<%s> %s|' % (self.userNick, msg.replace('|', '_')))
		else:
			self.cmdQueue.append('$To: %s From: %s $<%s> %s|' % (nick, self.userNick, self.userNick, msg.replace('|', '_')))
		self.opLock.release()

	def poll(self):
		try:
			if self._status == 0:
				if self.delay != None:
					curtime = time.time()

					self.delay[0] -= curtime - self.delay[1]
					if self.delay[0] <= 0:
						self.delay = None
					else:
						self.delay[1] = curtime
						return 0

				self.appendLogRow(self.LOG_STATUS, "Connecting to " + self._addr[0] + ":" + str(self._addr[1]) + "...")
				self.sock = AsyncSocket()
				self.sock.connect(self._addr)
				self.setStatus(1)

			elif self._status == 1:
				self.sock.poll()
				if self.sock.isConnected():
					self.appendLogRow(self.LOG_STATUS, "Connection established.")
					self.log.appendLogRow(self.LOG_STATUS, "Connection established.")
					self.log.appendLogRow2(self.LOG_STATUS, "Connection established.")
					self.setStatus(2)
					self.bot.start()

			elif self._status == 2:
				curtime = int(time.time())
				if curtime-self.lasttime>=1:
					self.lasttime=curtime
					self.bot.sendAnswers()
				self.opLock.acquire()
				if self.logged:
					for cmd in self.cmdQueue:
						self.sock.send(cmd)
				
				self.cmdQueue = []
				self.opLock.release()

				finished = self.sock.poll()
				self.buf += self.sock.recv()
				if len(self.buf) > 0:
					cmds = self.buf.split('|')
					if self.buf[-1] != "|":
						self.buf = cmds[-1]
						cmds = cmds[:-1]
					else:
						self.buf = ""

					for i in cmds:
						if len(i) > 0:
							res = self.parseCmd(i)
							if res == 0:
								self.setStatus(6)
								return 0
							elif res == 1:
								self.setStatus(3)
								return 0

				if finished:
					print "Connection closed."
					self.appendLogRow(self.LOG_ERROR, "Connection closed.")
					self.log.appendLogRow(self.LOG_STATUS, "Connection closed.")
					self.log.appendLogRow2(self.LOG_STATUS, "Connection closed.")
					self.checkReconnection()

			elif self._status == 3:
				self.sock.close()
				if self.sock.poll():
					self.removeAllUsers()

					self.opLock.acquire()
					self.reset()
					if self._status == 3: self._status = 0
					self.opLock.release()

					self.lock.acquire()
					for listener in self.listeners:
						listener.onHubInfo(self)
					self.lock.release()

			elif self._status == 4:
				self.sendCmd('Quit', self.userNick)
				self.sock.poll()
				self.setStatus(5)
				
			elif self._status == 5:
				if self.sock.getBytesToSend() > 0:
					self.sock.poll()
				else:
					self.setStatus(6)

			elif self._status == 6:
				if self.sock != None:
					self.sock.close()
					if not self.sock.poll():
						return 0

				self.opLock.acquire()
				self.reset()
				self._status = 7
				self.opLock.release()

				self.removeAllUsers()

				self.lock.acquire()
				for listener in self.listeners:
					listener.onHubDisconnection(self)
				self.lock.release()
				self.bot.stop()
				self.delay = [self.RECONNECTION_DELAY*3, time.time()]
				self._status = 0
				return 1

			else:
				self.delay = [self.RECONNECTION_DELAY*3, time.time()]
				self._status = 0
				return 1

		except DNSError:
			self.appendLogRow(self.LOG_ERROR, 'Connection closed because of DNS error.')
			self.log.appendLogRow2(self.LOG_ERROR, 'Connection closed because of DNS error.')
			self.setStatus(6)
			print 'Connection closed because of DNS error.'

		except error:
			self.appendLogRow(self.LOG_ERROR, 'Connection closed because of socket error.')
			self.log.appendLogRow2(self.LOG_ERROR, 'Connection closed because of socket error.')
			self.checkReconnection()
			print 'Connection closed because of socket error.'
		except:
			print "dchub Unexpected error:", sys.exc_info()[0]
			self.log.appendLogRow2(self.LOG_ERROR, "dchub Unexpected error:"+( sys.exc_info()[0]))

		return 0

	def stop(self):
		self.opLock.acquire()

		log = None
		if self._status < 4:
			self._status = (6, 6, 4, 6)[self._status]

			log = (self.LOG_STATUS, 'Connection aborted by user.\n')
			self._log.append(log)


		self.opLock.release()
		self.bot.stop()

		if log:
			self.lock.acquire()
			for listener in self.listeners:
				listener.onLogUpdate(self, log)
			self.lock.release()

	def getAddress(self):
		return self._addr

	def getName(self):
		return self._name

	def getUserNum(self):
		return len(self._users)

	def getUsers(self):
		self.opLock.acquire()
		users = []
		for user in self._users:
			users.append(self._users[user])
		self.opLock.release()

		return users

	def getUserByNick(self, nick):
		self.opLock.acquire()
		try:
			user = self._users[nick]
		except KeyError:
			user = None
		self.opLock.release()

		return user

	def getSize(self):
		return self._size

	def getLogRows(self):
		return self._log

	def getStatus(self):
		return (self.STATUS_CONNECTING,
			  self.STATUS_CONNECTING,
			  self.STATUS_CONNECTED,
			  self.STATUS_CONNECTING,
			  self.STATUS_CLOSED,
			  self.STATUS_CLOSED,
			  self.STATUS_CLOSED,
			  self.STATUS_CLOSED)[self._status]

	def isAlive(self):
		return (1,1,1,1,0,0,0,0)[self._status]

	#=================#
	# Private members #
	#=================#

	def parseAddress(self, addr):
		if addr.__class__ == str:
			pos = addr.find(':') 
			if pos != -1:
				try:
					return (addr[:pos], int(addr[pos+1:]))
				except ValueError:
					self.appendLogRow(self.LOG_ERROR, "Invalid address: \"" + addr + "\".")
					self.setStatus(6)
					return None
			else:
				return (addr, 411)
		else:
			return addr
			
	def checkReconnection(self):
		if self._status == 2 and self.logged and self.getUserNum() > 0:
			self.delay = [self.RECONNECTION_DELAY, time.time()]
			self.setStatus(3)
			self.appendLogRow(self.LOG_STATUS, "Reconnecting in %d seconds..." % self.delay[0])
		else:
			self.setStatus(6)

	def setStatus(self, status):
		self.opLock.acquire()
		if status > self._status:
			self._status = status
		self.opLock.release()

	def buildInfo(self):
		user = DCWorker.getWorker().getUser()
		info = "$ALL " + self.userNick + " "
		if user.description != None:
			info += user.description
		mode='P'
		if DCWorker.getWorker().getSettings().getMode():
			mode='A'
		info += "<botDC V:0.6,M:"+mode+",H:1/1/0,S:3>"

		info += "$ $"
		if user.connection == DCUser.CONN_56K:
			info += "56Kbps"
		elif user.connection == DCUser.CONN_SATELLITE:
			info += "Satellite"
		elif user.connection == DCUser.CONN_DSL:
			info += "DSL"
		elif user.connection == DCUser.CONN_CABLE:
			info += "Cable"
		elif user.connection == DCUser.CONN_T1:
			info += "LAN(T1)"
		elif user.connection == DCUser.CONN_T3:
			info += "LAN(T3)"
		info += chr(self.userStatus) + "$"

		if user.email != None:
			info += user.email
		info += "$"

		if user.share == -1:
			info += "0"
		else:
			info += str(user.share)
		info += "$"

		return info

	def appendLogRow(self, type, text):
		self.opLock.acquire()
		row = (type, text + '\n')
		self._log.append(row)
		if len(self._log) > DCHub.MAX_LOG_ROWS:
			del self._log[0]
		self.opLock.release()

		self.lock.acquire()
		for listener in self.listeners:
			listener.onLogUpdate(self, row)
		self.lock.release()

	def addUser(self, user, askinfo = 1):
		if len(user.nick) == 0 or user.nick == self.userNick: return
		if self._users.has_key(user.nick):
			if user.op: self._users[user.nick].op = 1
			return

		user.hub = self
		if askinfo and user.connection == DCUser.CONN_NONE:
			self.sendCmd("GetINFO", user.nick, self.userNick)

		self.opLock.acquire()
		self._users[user.nick] = user
		self.opLock.release()

		self.lock.acquire()
		for listener in self.listeners:
			listener.onNewUser(self, user)
		self.lock.release()

	def removeUser(self, nick):
		self.opLock.acquire()
		try:
			user = self._users[nick]
		except KeyError:
			self.opLock.release()
			return

		user.hub = None
		if user.share > 0:
			self._size -= user.share

		del self._users[nick]
		self.opLock.release()

		self.lock.acquire()
		for listener in self.listeners:
			listener.onUserDisconnection(self, user)
		self.lock.release()

	def removeAllUsers(self):
		self.opLock.acquire()
		users = self._users
		self._users = {}
		self._size = 0
		self.opLock.release()

		self.lock.acquire()
		for listener in self.listeners:
			for nick in users:
				listener.onUserDisconnection(self, users[nick])
		self.lock.release()

	def parseCmd(self, cmd):
		#if cmd.find("$UserCommand")<0:
		#print "From Hub: " + cmd
		if cmd[0] == '<': #Chat message
			self.appendLogRow(self.LOG_CHAT, cmd)
			try:
				cmd = cmd[1:]
				pos = cmd.index('>')
				nick = cmd[:pos]				
				#self.appendLogRow(self.LOG_CHAT, '<%s> %s' % (nick, cmd[idx+2:]))
				#if len(self.awayMsg)>0:
				#	self.sendMsg(self.awayMsg,nick)
				if cmd[pos+1]==' ':
					msg=cmd[pos+2:]
				else:
					msg=cmd[pos+1:]
				#print '%s|%s' % (nick, cmd[pos+2:])
				#time=time.time()
				self.bot.processMsg(nick,msg)
				self.log.appendLogRow2(7,('<%s> %s' % (nick, msg)))
				if msg.find(self.userNick)>=0:
					self.log.appendLogRow(7,('<%s> %s' % (nick, msg)))
			except ValueError: pass
			return 2
		elif cmd[0] != "$":
			self.appendLogRow(self.LOG_ERROR, "Unknown command: " + cmd)
			#print "1Unknown command: " + cmd
			return 2
			
		cmd = cmd[1:]
		try:
			pos = cmd.index(' ')
			cmdname = cmd[:pos]
		except ValueError:
			if cmd == "HubIsFull":
				self.appendLogRow(self.LOG_ERROR, "Hub is full; disconnected.")
				return 0
			else:
				#Discard silently
				#print "1Unknown command: " + cmd
				if cmd!="GetPass" and cmd!="Supports":
					return 0
				else:
					cmdname=cmd

		if cmdname == "Hello":
			if self.userNick == cmd[pos+1:]:				
				self.sendCmd("Version", "1.3")
				self.sendCmd("GetNickList")
				self.sendCmd("MyINFO", self.buildInfo())
			else:
				user = DCUser()
				user.nick = cmd[pos+1:]
				self.addUser(user)

		elif cmdname == "MyINFO":
			try:
				if cmd[pos+1:pos+6] != "$ALL ": return 2
				cmd = cmd[pos+6:]

				#Nick
				pos = cmd.index(" ")
				nick = cmd[:pos]
				cmd = cmd[pos+1:]

				if nick == self.userNick:
					self.logged = 1
					return 2

				try:
					user = self._users[nick]
				except KeyError:
					user = DCUser()
					user.nick = nick
					self.addUser(user, 0)

				#Description
				pos = cmd.index("$ $")
				if pos != 0:
					user.description = cmd[:pos]
				else:
					user.description = None
				cmd = cmd[pos+3:]

				#Split remaining fields
				fields = cmd.split("$")
				if len(fields) != 4:
					raise ValueError
				if len(fields[3]) > 0:
					raise ValueError

				#Connection
				fields[0] = fields[0][:-1]	#get rid of speed class byte
				if fields[0] == "56Kbps":
					user.connection = DCUser.CONN_56K
				elif fields[0] == "Satellite":
					user.connection = DCUser.CONN_SATELLITE
				elif fields[0] == "DSL":
					user.connection = DCUser.CONN_DSL
				elif fields[0] == "Cable":
					user.connection = DCUser.CONN_CABLE
				elif fields[0] == "LAN(T1)":
					user.connection = DCUser.CONN_T1
				elif fields[0] == "LAN(T3)":
					user.connection = DCUser.CONN_T3

				#Email
				if len(fields[1]) != 0:
					user.email = fields[1]
				else:
					user.email = None

				#Share
				user.share = long(fields[2])
				self._size += user.share

				#Notify listeners of changes
				self.lock.acquire()
				for listener in self.listeners:
					listener.onUserInfo(self, user)
				self.lock.release()

			except ValueError:
				pass

		elif cmdname == "Search":
			#cmd = cmd[7:]
			pass
			#try:
			#	p1, p2 = cmd.index(':'), cmd.index(' ')
			#	addr = cmd[:p1]
			#	if addr == "Hub":
			#		activeSearch = 0
			#		addr = cmd[p1+1:p2]
			#	else:
			#		activeSearch = 1
			#		addr = (addr, int(cmd[p1+1:p2]))

			#	params = cmd[p2+1:].split('?')
			#	if len(params) != 5:
			#		raise ValueError
					
			#	if params[0] == 'F':
			#		limit = DCFileList.LIMIT_NONE
			#		size = 0
			#	else:
			#		if params[1] == 'F':
			#			limit = DCFileList.LIMIT_ATLEAST
			#		else:
			#			limit = DCFileList.LIMIT_ATMOST

			#		size = long(params[2])

			#	worker = DCWorker.getWorker()
			#	slots = [worker.getSettings().slots - worker.getUsedSlots(), worker.getSettings().slots]
			#	hubAddr = self.sock.getpeername()
				
				#Safety check
			#	if hubAddr == None: return 0

				#for i in worker.getLocalLists():
				#	for r in i.search(params[4].replace('$', ' '), limit, size):
				#		data =  '$SR %s %s\5%d %d/%d\5%s (%s:%d)' % (self.userNick, r.getPath(), r.size, slots[0], slots[1], self._name, hubAddr[0], hubAddr[1])
				#		if activeSearch:
				#			worker.getSearchWorker().sendResult(addr, data + '|')
				#		else:
				#			data += '\5%s|' % addr
				#			self.sock.send(data)

			#except ValueError:
			#	pass
				
		elif cmdname == 'SR':
			#DCWorker.getWorker().getSearchWorker().passiveResult(cmd[pos+1:])
			pass

		elif cmdname == "Quit":
			self.removeUser(cmd[pos+1:])

		elif cmdname == "To:":
			try:
				idx = cmd.index('$') - 1
				nick = cmd[cmd[:idx].rindex(' ')+1:idx]
				self.appendLogRow(self.LOG_PRIVCHAT, '<%s> %s' % (nick, cmd[idx+2:]))
				self.log.appendLogRow(self.LOG_PRIVCHAT, '<%s> %s' % (nick, cmd[idx+2:]))
				if len(self.awayMsg)>0:
					self.sendMsg(self.awayMsg,nick)
			except ValueError: pass

		elif cmdname == "ConnectToMe":
			addr = cmd[cmd.rindex(' ')+1:].split(':')
			try: addr = (addr[0], int(addr[1]))
			except ValueError: pass

			#sock = AsyncSocket()
			#sock.connect(addr)
			#DCWorker.getWorker().addJob(DCXfer(sock))
			
		elif cmdname == 'RevConnectToMe':
                	if not DCWorker.getWorker().getSettings().active: return 2
			self.requireConnection(cmd[cmd.index(' ')+1:cmd.rindex(' ')])
			
		elif cmdname == "LogedIn":
			if self.userNick == cmd[pos+1:]:
				self.op=1
			else:
				user = DCUser()
				user.op = 1
				user.nick = cmd[pos+1:]
				self.addUser(user)

		elif cmdname == "NickList":
			nicks = cmd[pos+1:].split("$$")

			for nick in nicks:
				user = DCUser()
				user.nick = nick
				self.addUser(user)

		elif cmdname == "OpList":
			nicks = cmd[pos+1:].split("$$")

			for nick in nicks:
				user = DCUser()
				user.op = 1
				user.nick = nick
				self.addUser(user)

		elif cmdname == "ForceMove":
			newAddr = cmd[pos+1:]
			if len(newAddr) == 0: return 0

			addr = self.parseAddress(newAddr)
			if addr == None: return 0

			self.appendLogRow(self.LOG_STATUS, "Redirected to \"" + newAddr + "\".")
			self._addr = addr
			
			return 1

		elif cmdname == "Lock":
			self.key = solveChallenge(cmd[pos+1:])
			if len(self.key) == 0:
				self.appendLogRow(self.LOG_ERROR, "Error while generating authkey.")
				return 0
			
			#if cmd[pos+1:].find("EXTENDEDPROTOCOL")>=0:
			#	self.sendCmd("Supports", "UserIP2")
			
			self.sendCmd("Key", self.key)
			self.sendCmd("ValidateNick", self.userNick)
			if len(self.userPasswd)>0:
				self.sendCmd("MyPass",self.bot.toServerCharset(self.userPasswd))
				#print "Sent passwd"
			
			

		elif cmdname == "Supports":
			pass
			#self.sendCmd("Supports", "UserIP2")
			#self.sendCmd("Key", self.key)
			#self.sendCmd("ValidateNick", self.userNick)
			#self.sendCmd("Version", "1.3")

			#self.sendCmd("MyINFO", self.buildInfo())
			#self.sendCmd("GetNickList")

		elif cmdname == "HubName":
			self._name = cmd[pos+1:]

			self.lock.acquire()
			for i in self.listeners:
				i.onHubInfo(self)
			self.lock.release()

		elif cmdname == "GetPass":
			#print "MyPass " + self.userPasswd
			#self.appendLogRow(self.LOG_ERROR, "Hub requires password. Function not yet implemented.")
			if len(self.userPasswd)==0:
				self.appendLogRow(self.LOG_ERROR, "Hub requires password. No passwd.")
				return 0
			
			#self.sendCmd("MyPass",self.bot.toServerCharset(self.userPasswd))
			self.appendLogRow(self.LOG_STATUS, "Hub requires password. Sent.")
			#print "MyPass " + self.userPasswd
			#return 0

		elif cmdname == 'ValidateDenide':
			#print "Unknown command ValidateDenide: " + cmd
			self.appendLogRow(self.LOG_ERROR, "Authentication error; disconnected.")
			return 0

		#else:
		#	self.appendLogRow(self.LOG_ERROR, "Unknown command: " + cmd)
		#print "3Unknown command: " + cmd
		return 2

	def sendCmd(self, cmd, *args):
		cmdstr = "$" + cmd
		for i in args:
			cmdstr += " " + i
		cmdstr += "|"

		self.sock.send(cmdstr)
		#print "To hub: "+cmdstr
	
	def getHubUrl(self):
		return self.getAddress()[0]+":"+str(self.getAddress()[1])

	address = property(getAddress, None, None, None)
	name = property(getName, None, None, None)
	userNum = property(getUserNum, None, None, None)
	users = property(getUsers, None, None, None)
	size = property(getSize, None, None, None)
	logRows = property(getLogRows, None, None, None)
	status = property(getStatus, None, None, None)

class AddressAlreadySetError(Exception): pass

class DCLog:
	def __init__(self,logdir):
		self.log=1
		try:
			self.f=open(logdir+"/answers.log","a+");
			self.f2=open(logdir+"/all.log","a+");
		except:
			print "open Unexpected error:", sys.exc_info()
	def appendLogRow(self, type1, text):
		if self.log<1:return
		if text==None:return
		try:
			self.f.write('['+str(time.strftime("%d %b %Y %H:%M:%S"))+']	('+str(type1)+')	'+text+'\n')
		except:
			pass
	def appendLogRow2(self, type1, text):
		if self.log<1:return
		if text==None:return
		try:
			self.f2.write('['+str(time.strftime("%d %b %Y %H:%M:%S"))+']	('+str(type1)+')	'+text+'\n')
		except:
			pass
	def flush(self):
		try:
			self.f.flush()
		except:
			pass
	def close(self):
		self.f.close()
		self.f2.close()


import json
from collections import deque
import httplib, urllib
class DCBot:
	def __init__(self,hub1,settings1):
		self.queue=deque()
		self.connect=0
		self.hub=hub1
		self.settings=settings1

		self.iDelayStart = 5
		self.sPathToPid = ".aibot.pid"
		self.tHub={
			'iVer' : 100,
			'tDelay' : [ 5,7 ]
			}
		self.iMsgCount=0
		self.sUrl  = self.settings.getAIBotUrl()
		#sUrl = None
		self.sCookie = '0'
		self.bOn=0
		self.iStartTime=0
		self.sLang='ru'
		self.sCharset='utf-8'
		self.sHubUrl=hub1.getHubUrl()

		self.dump=0

		#self.load()

	def start(self):
		if self.bOn==1:
			return
		self.iStartTime=int(time.time())
		if self.dump:print 'connecting...'
		params = self.tojson({'nick':self.toServerCharset(self.hub.getUserNick()),'hub':self.tHub,'hubname':self.sHubUrl,'msg':'pub','cookie':self.sCookie})
			
		headers = {#"Content-Length" : string.len(request_body),   
				"Content-Type" :  "text/plain;charset="+self.sCharset,
				"Content-Language" : self.sLang,
				"Cookie" : self.sCookie}
		try:
			conn = httplib.HTTPConnection(self.sUrl)
			conn.request("POST", "/connect", params, headers)
			response = conn.getresponse()
			
			#print response 
			if response.status==200:
				#print response.reason
				#print response.msg
				#print response.version
				data = response.read()
				conn.close()
				#print str(data)
				o=self.fromjson(data)
				self.sCookie=o.get('cookie')
				if self.dump:print self.sCookie
				self.iMsgCount=0
				self.queue.clear()	
				self.bOn=1	
				self.hub.getLog().appendLogRow(self.hub.LOG_STATUS,"aibot connected")	
			else:
				conn.close()	
				if self.dump:print str(response.status)
				
		except:
			print "start Unexpected error:", sys.exc_info()
		
	def toServerCharset(self,s):
		if s==None:return ''
		if s.__class__ == int :return str(s)
		if s.__class__ == long :return str(s)
		if s.__class__ == str:			
			return s.decode(self.settings.getCodePage()).encode(self.sCharset)

		elif s.__class__ == dict:
			if len(s) == 0: return ''

			for k in s.iterkeys():
				s[k]=self.toServerCharset(s[k])

			return s

		else:
			if self.dump:print "Parameter not supported. "+str(s.__class__)+" "+str(s)
			return str(s)
		#print x
		#x=x.decode(self.settings.getCodePage()).encode(self.sCharset)
		#print x
		#return x
	def fromServerCharset(self,s):
		return s.encode(self.settings.getCodePage())

	def tojson(self,s):
		return json.dumps(s)
		
	def fromjson(self,s):
		return json.loads(s)

	def stop(self):
		if self.bOn==0:
			return
		
		params = self.tojson({'hubname':self.sHubUrl,'msg':'pub','cookie':self.sCookie})
		
		headers = {#"Content-Length" : string.len(request_body),   
				"Content-Type" :  "text/plain;charset="+self.sCharset,
				"Content-Language" : self.sLang,
				"Cookie" : self.sCookie}
		try:
			conn = httplib.HTTPConnection(self.sUrl)
			conn.request("POST", "/disconnect", params, headers)
			response = conn.getresponse()
			conn.close()			
			if self.dump:print str(response.status) + " disconnected"			
				
		except:
			print "stop Unexpected error:", sys.exc_info()			
		self.bOn=0	
		self.sCookie='0'
		self.iMsgCount=0
		self.queue.clear()
		self.hub.getLog().appendLogRow(self.hub.LOG_STATUS,"aibot disconnected")	

	def processMsg(self,nick,msg): #bot.processMsg(nick,msg)
		if self.bOn==0:
			return
		if nick==self.hub.getUserNick():
			return
		curtime=int(time.time())
		
		if curtime<=self.iStartTime+self.iDelayStart:
			return
		#request_body = json.encode({user=tUser,data=convertToUtf8(sData),hubname=sHub,msg="pub"})			
		#print msg
		user = self.hub.getUserByNick(nick)
		if user == None:
			tUser = {
			'NI':nick,
			'DE':'',
			'EM':'',
			'SSshort':0,
			'SS':0,
			'TA':'',
			'HL':'',
			}
		else:			
			tUser=user.gettUser()
		#print tUser
		params = self.tojson({'user':self.toServerCharset(tUser),'data':self.toServerCharset(msg),'hubname':self.sHubUrl,'msg':'pub'})
		#print params
		headers = {#"Content-Length" : string.len(request_body),   
				"Content-Type" :  "text/plain;charset="+self.sCharset,
				"Content-Language" : self.sLang,
				"Cookie" : self.sCookie}
		try:
			conn = httplib.HTTPConnection(self.sUrl)
			conn.request("POST", "/message", params, headers)
			response = conn.getresponse()
			conn.close()

			if response.status==200:
				self.iMsgCount+=1
				if self.dump>1:print "sent "+msg
		except:
			print "processMsg Unexpected error:", sys.exc_info()[0]

		
		

	def sendAnswers(self):
		if self.dump>2:print self.iMsgCount
		if self.bOn==0 or self.iMsgCount<=0:
			return		
		#curtime=time.time()
		#self.queue[0].get()
		params = self.tojson({'hubname':self.sHubUrl,'msg':'pub'})
		
		headers = {#"Content-Length" : string.len(request_body),   
				"Content-Type" :  "text/plain;charset="+self.sCharset,
				"Content-Language" : self.sLang,
				"Cookie" : self.sCookie}
		#print params
		try:
			conn = httplib.HTTPConnection(self.sUrl)
			conn.request("POST", "/answer", params, headers)
			response = conn.getresponse()
			#print str(response.status)
			if response.status==200:
				data = response.read()
				conn.close()
				
				o=self.fromjson(data)
				sMsg=o.get('msg')
				iCount=int(o.get('count'))				
				self.iMsgCount-=iCount
				if self.iMsgCount<=0:
					self.iMsgCount=0
				if len(sMsg)>0:
					self.hub.sendMsg(self.fromServerCharset(sMsg))		
					sQ=o.get('q')
					self.hub.getLog().appendLogRow(6,self.fromServerCharset(sQ))
					self.hub.getLog().appendLogRow(9,self.fromServerCharset(sMsg))

				if self.dump>1:print "got msg="+sMsg+" count"+str(iCount)
			else:
				conn.close()
		except:
			print "sendAnswers Unexpected error:", sys.exc_info()			




	
